package com.lagou.provider.handle;

import com.alibaba.fastjson.JSON;
import com.lagou.api.com.RpcRequest;
import com.lagou.api.com.RpcResponse;
import com.lagou.provider.annotations.RpcService;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.springframework.beans.BeansException;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;


@Component
@ChannelHandler.Sharable
public class ServiceHandle extends SimpleChannelInboundHandler<String> implements ApplicationContextAware {

    /**
     * 服务map
     */
    private static final Map SERVICE_MAP = new ConcurrentHashMap();


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String,Object> beanMap = applicationContext.getBeansWithAnnotation(RpcService.class);
        if (beanMap != null && beanMap.size() > 0 ){
            Set<Map.Entry<String, Object>> entries =  beanMap.entrySet();
            for (Map.Entry<String, Object> entry : entries){
                Object serviceBean = entry.getValue();
                if (serviceBean.getClass().getInterfaces().length == 0) {
                    throw new RuntimeException("服务必须实现接口");
                }else {
                    SERVICE_MAP.put(serviceBean.getClass().getInterfaces()[0].getName(),serviceBean);
                }
            }
        }
    }


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception {
        RpcRequest rpcRequest =  JSON.parseObject(msg, RpcRequest.class);
        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setRequestId(rpcRequest.getRequestId());
        try {
          Object object = handle(rpcRequest);
          rpcResponse.setResult(object);
        }catch (Exception e){
          e.printStackTrace();
          rpcResponse.setError(e.getMessage());
        }
        channelHandlerContext.writeAndFlush(JSON.toJSONString(rpcResponse));
    }

    private Object handle(RpcRequest rpcRequest) throws Exception {
        Object serviceBean = SERVICE_MAP.get(rpcRequest.getClassName());
        if (serviceBean == null){
           throw new Exception("没有找到服务");
        }
        Class<?> serviceBeanClass = serviceBean.getClass();
        String methodName = rpcRequest.getMethodName();
        Object[] parameters = rpcRequest.getParameters();
        FastClass fastClass = FastClass.create(serviceBeanClass);
        FastMethod fastMethod = fastClass.getMethod(methodName,rpcRequest.getParameterTypes());
        return  fastMethod.invoke(serviceBean,parameters);
    }


}
